package com.nt.thah.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.*;

/**
 * @Description: http工具类
 * @author: ls
 * @Date: 2020/7/10 15:52
 */
@Slf4j
public class HttpClientUtils {

    public static RequestConfig requestConfig;
    public static final String charset = "UTF-8";
    public static final String HTTP_KEYSTORE_TYPE = "PKCS12";
    public static final String HTTP_SUPPORTED_PROTOCOLS_TLS_V1 = "TLSv1";
    public static final String HTTP_PROTOCOL_TYPE_HTTPS = "https";
    public static final int POOLING_MAX_TOTAL = 100;
    public static final int POOLING_MAX_PRE_ROUTE = 20;
    public static final int KEEP_ALIVE = 5000;

    static {
        requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();
    }

    /**
     * @Description： 创建HttpsClient
     * @Author: ls
     * @Date: 2021/4/26 3:21 下午
     */
    public static CloseableHttpClient createHttpsClient(String keyStorePath, String keyStorePassword) {
        CloseableHttpClient build = null;
        InputStream is = null;
        try {
            is = HttpClientUtils.class.getClassLoader().getResourceAsStream(keyStorePath);
            KeyStore keyStore = KeyStore.getInstance(HTTP_KEYSTORE_TYPE);
            keyStore.load(is, keyStorePassword.toCharArray());
            SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, keyStorePassword.toCharArray()).build();
            SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext,
                    new String[]{HTTP_SUPPORTED_PROTOCOLS_TLS_V1}, null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.<ConnectionSocketFactory>create();
            Registry<ConnectionSocketFactory> socketFactoryRegistry = builder.register(HTTP_PROTOCOL_TYPE_HTTPS, factory).build();
            PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            manager.setMaxTotal(POOLING_MAX_TOTAL);
            manager.setDefaultMaxPerRoute(POOLING_MAX_PRE_ROUTE);
            ConnectionKeepAliveStrategy strategy = new DefaultConnectionKeepAliveStrategy() {
                @Override
                public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                    long keepAlive = super.getKeepAliveDuration(response, context);
                    if (keepAlive == -1) {
                        keepAlive = KEEP_ALIVE;
                    }
                    return keepAlive;
                }
            };
            build = HttpClients.custom().setSSLSocketFactory(factory).setConnectionManager(manager).setKeepAliveStrategy(strategy).build();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return build;
    }

    /**
     * @Description: post请求-参数支持json字符串、map、JSONObject
     * @author: ls
     * @Date: 2020/7/10 15:57
     */
    public static JSONObject httpPost(String url, Object obj, Header[] headers) {
        JSONObject jsonObject = new JSONObject();
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeaders(headers);
        // 设置请求和传输超时时间
        httpPost.setConfig(requestConfig);
        try {
            if (null != obj) {
                StringEntity entity;
                if (obj instanceof String) {
                    entity = new StringEntity(obj.toString(), charset);
                } else {
                    entity = new StringEntity(JSON.toJSONString(obj), charset);
                }
                entity.setContentEncoding(charset);
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            response = httpClient.execute(httpPost);
            jsonObject = buildResult(response);
        } catch (Exception e) {
            log.error("post请求提交失败:", e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpPost.releaseConnection();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonObject;
    }


    /**
     * @Description: post请求返回字符串-参数支持json字符串、map、JSONObject
     * @author: ls
     * @Date: 2020/7/10 15:57
     */
    public static String postReturnStr(CloseableHttpClient httpClient, String url, Object obj) {
        String result = "";
        StringBuilder requestText = new StringBuilder();
        CloseableHttpResponse response = null;
        if(httpClient == null) {
            httpClient = HttpClients.createDefault();
        }
        HttpPost httpPost = new HttpPost(url);
        // 设置请求和传输超时时间
        httpPost.setConfig(requestConfig);
        try {
            if (null != obj) {
                StringEntity entity;
                if (obj instanceof String) {
                    entity = new StringEntity(obj.toString(), charset);
                } else {
                    entity = new StringEntity(JSON.toJSONString(obj), charset);
                }
                entity.setContentEncoding(charset);
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            response = httpClient.execute(httpPost);
            byte[] x = EntityUtils.toByteArray(response.getEntity());
            requestText.append(new String(x, StandardCharsets.UTF_8));
            result = requestText.toString();
        } catch (Exception e) {
            log.error("post请求提交失败:", e);
        } finally {
            close(response);
        }
        return result;
    }

    /**
     * @Description: post请求传输String参数 例如：name=Jack&sex=1&type=2
     * Content-type:application/x-www-form-urlencoded
     * @author: ls
     * @Date: 2020/7/21 14:05
     */
    public static JSONObject httpPostForm(String url, Map<String, String> params, Header[] headers) {
        JSONObject jsonObject = new JSONObject();
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        httpPost.setHeaders(headers);
        try {
            if (!CollectionUtils.isEmpty(params)) {
                List<NameValuePair> paramList = new ArrayList<NameValuePair>();
                Set<String> keySet = params.keySet();
                for (String key : keySet) {
                    paramList.add(new BasicNameValuePair(key, params.get(key)));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(paramList, charset));
            }
            response = httpClient.execute(httpPost);
            jsonObject = buildResult(response);
        } catch (IOException e) {
            log.error("post请求提交失败:", e);
        } finally {
            close(response);
        }
        return jsonObject;
    }

    /**
     * @Description: 发送get请求
     * @author: ls
     * @Date: 2020/7/10 16:00
     */
    public static JSONObject httpGet(String url, Header[] headers) {
        JSONObject jsonResult = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet request = new HttpGet(url);
        request.setConfig(requestConfig);
        request.setHeaders(headers);
        try {
            response = client.execute(request);
            jsonResult = buildResult(response);
        } catch (Exception e) {
            log.error("get请求提交失败:" + url, e);
        } finally {
            close(response);
        }
        return jsonResult;
    }

    /**
     * @Description: 处理请求结果
     * @author: ls
     * @Date: 2020/7/10 16:00
     */
    public static JSONObject buildResult(CloseableHttpResponse response) {
        JSONObject jsonObject = new JSONObject();
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            String strResult = null;
            try {
                strResult = EntityUtils.toString(entity, "utf-8");
            } catch (IOException e) {
                log.error("解析结果错误:", e);
            }
            jsonObject = JSONObject.parseObject(strResult);
            jsonObject.put("headers", response.getAllHeaders());
        } else {
            log.error(" {} ", response);
        }
        return jsonObject;
    }

    /**
     * @Description： 关闭响应
     * @Author: ls
     * @Date: 2021/4/26 3:17 下午
     */
    public static void close(CloseableHttpResponse response) {
        if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @Description: 发送get请求
     * @author: ls
     * @Date: 2020/7/10 16:00
     */
    public static String httpGetString(String url, Header[] headers) {
        String result = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet request = new HttpGet(url);
        request.setConfig(requestConfig);
        request.setHeaders(headers);
        try {
            response = client.execute(request);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                try {
                    result = EntityUtils.toString(entity, "utf-8");
                } catch (IOException e) {
                    log.error("解析结果错误:", e);
                }
            }
        } catch (Exception e) {
            log.error("get请求提交失败:" + url, e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                request.releaseConnection();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static void main(String[] args) {
//        Map<String, Object> params = new TreeMap<>();
//        String url = "http://api.kaminlm.com/v2/product";
//        params.put("cid", "20");
//        params.put("timestamp", System.currentTimeMillis() / 1000);
//        Map<String, Object> sortParams = OpenCardSignUtils.sortParams(params);
//        String signStr = OpenCardSignUtils.joinParams(sortParams);
//        String sign = OpenCardSignUtils.md5(OpenCardSignUtils.md5(signStr) + "65jqu0oc1g").toUpperCase(Locale.ROOT);
//        params.put("sign", sign);
//        JSONObject result = HttpClientUtils.httpPost(url, params, null);
//        System.out.println(result);

//        HttpHead reqHeader = new HttpHead();
//        reqHeader.addHeader("userToken", "38755809502175232x585c091fdc834fbc5e93dae83650c5dd");
//        reqHeader.addHeader("Cookie", "sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221831b11d7bf98d-007c5010db20a89-646a0a13-304500-1831b11d7c0866%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%221831b11d7bf98d-007c5010db20a89-646a0a13-304500-1831b11d7c0866%22%7D; acw_tc=781bad3416626439563445952e32c5fa76a128a7a9a52465ef567a090a78b4; sajssdk_2015_cross_new_user=1");
//        String url = "https://vipservice.vcredit.com/vcp/vmc-benefits-service/benefits/external/customer/loanInvite/queryIncomeInviteList";
//        Map<String, Object> params = new TreeMap<>();
//        params.put("activityType", "mgm_yqfx_xj_v2");
//        JSONObject result = HttpClientUtils.httpPost(url, params, null);
//        System.out.println(result);
//
        String url = "http://www.vzoom.com/vzoom-partner-backend/pingAnFeedback/page?timestamp=1682062765955";
        HttpHead reqHeader = new HttpHead();
        reqHeader.addHeader("Cookie", "JSESSIONID=007C5016FA92F7A9502BC0F6D1ECAF70");
        Map<String, String> reqParam = Maps.newHashMap();
        reqParam.put("brokerPlatformId", "XWDSCWZXK10");
        reqParam.put("current", "1");
        reqParam.put("phoneNo", "");
        reqParam.put("productType", "8");
        reqParam.put("size", "10");
        JSONObject result = HttpClientUtils.httpPost(url, reqParam, reqHeader.getAllHeaders());
        System.out.println(result);

//        Map<String, String> reqParam = Maps.newHashMap();
//        String url = "https://servicewechat.com/DirectBank/bydMarket/getCustomerLink";
//        reqParam.put("imageNo", "");
//        reqParam.put("userId", "LS63");
//        reqParam.put("orgId", "SZHDX");
//        reqParam.put("benchmarkLevel", "28");
//        reqParam.put("theme", "");
//        reqParam.put("deviceOrientation", "portrait");
//        reqParam.put("brand", "iPhone");
//        reqParam.put("model", "iPhone X (GSM+CDMA)<iPhone10,3>");
//        reqParam.put("pixelRatio", "3");
//        reqParam.put("screenWidth", "375");
//        reqParam.put("screenHeight", "812");
//        reqParam.put("windowWidth", "375");
//        reqParam.put("windowHeight", "642");
//        reqParam.put("statusBarHeight", "44");
//        reqParam.put("language", "zh_CN");
//        reqParam.put("version", "8.0.32");
//        reqParam.put("system", "iOS 16.2");
//        reqParam.put("fontSizeSetting", "17");
//        reqParam.put("SDKVersion", "2.30.0");
//        reqParam.put("platform1", "ios");
//        reqParam.put("sysVersion", "iOS 16.2");
//        reqParam.put("appVersion", "8.0.32");
//        reqParam.put("mobileType", "iPhone X (GSM+CDMA)<iPhone10,3>");
//        reqParam.put("resolution", "1125*2436");
//        reqParam.put("reqChannelId", "17");
//        reqParam.put("networkType", "4g");
//        reqParam.put("location", "117.20624598046042,31.855160131259765");
//        reqParam.put("nProvince", "安徽省");
//        reqParam.put("nCityName", "合肥市");
//        reqParam.put("nCityCode", "");
//        reqParam.put("nDistrict", "蜀山区");
//        reqParam.put("adCode", "340104");
//        reqParam.put("macAddress", "");
//        reqParam.put("ipAddress", "");
//        reqParam.put("merType", "");
//        reqParam.put("grayFlag", "");
//        reqParam.put("cId", "");
//        reqParam.put("sessionId", "a9b98ff2103de91b7709f7e02b6a7ef8");
//        reqParam.put("oauthId", "5f6b6e6b47af9c10f545778f5aecb5b1");
//        reqParam.put("openId", "oBZXp5ff6l_H_4WCoSjKhnkQETxc");
//        JSONObject result = HttpClientUtils.httpPost(url, reqParam, null);
//        System.out.println(result);
    }
}

